using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FieldEngine : MonoSingleton<FieldEngine>, IResolveEngine<FieldModel>
{
  #region Inner Classes

  public abstract class MonoResolver : MonoBehaviour, IResolveEngine<FieldModel>.IResolver
  {
    public abstract void Resolve(IResolveEngine<FieldModel>.ResolveContext context);
  }

  public abstract class MonoHolder : MonoBehaviour, IResolveEngine<FieldModel>.IHolder
  {
    public abstract void Hold(IResolveEngine<FieldModel>.ResolveContext context);
    public abstract bool IsHolding();
    public abstract void Release();
  }

  #endregion
  [SerializeField]
  private List<MonoResolver> _staticResolver = new List<MonoResolver>();

  private ResolveEngineImpl<FieldModel> m_engineImpl = new ResolveEngineImpl<FieldModel>();

  private bool m_hasInited;

  public event Action onStableEvent {
    add {
      m_engineImpl.onStableEvent += value;
    }
    remove {
      m_engineImpl.onStableEvent -= value;
    }
  }

  public void InitIfNot() {
    if (m_hasInited)
    {
      return;
    }

    m_engineImpl.getListeningResolvers = GetListeningResolvers;
  }

  public void SetModel(FieldModel model) {
    m_engineImpl.SetModel(model);
  }

  public FieldModel GetStableModel() {
    return m_engineImpl.GetStableModel();
  }

  public void Tick() {
    m_engineImpl.Tick();
  }

  public void TriggerResolve(IResolveEngine<FieldModel>.IResolver resolver) {
    m_engineImpl.TriggerResolve(resolver);
  }

  public void TriggerEmptyResolve(IResolveEngine<FieldModel>.IHolder holder = null) {
    var resolver = new EmptyResolver<FieldModel>(holder);
    TriggerResolve(resolver);
  }

  private IEnumerable<MonoResolver> GetListeningResolvers() {
    var tmp = new List<MonoResolver>(_staticResolver);
    tmp.Reverse();
    return new List<MonoResolver>(tmp);
  }

  private void Update() {
    Tick();
  }

  public void RegisterHolder(string key, IResolveEngine<FieldModel>.IHolder holder) {
    ((IResolveEngine<FieldModel>)m_engineImpl).RegisterHolder(key, holder);
  }

  public void RegisterResolver(string key, IResolveEngine<FieldModel>.IResolver resolver) {
    ((IResolveEngine<FieldModel>)m_engineImpl).RegisterResolver(key, resolver);
  }
}
